#include <cctype>
#include <cstring>

#include "HugeInt.h"


HugeInt::HugeInt( long value )
{
    for( int i = 0; i <= 29; i++ )
        integer[ i ] = 0;

    for( int j = 29; value != 0 && j >= 0; j-- )
    {
        integer[ j ] = value % 10;
        value /= 10;
    }
}

HugeInt::HugeInt( const char *string )
{
    for( int i = 0; i <= 29; i++ )
        integer[ i ] = 0;

    int length = strlen( string );

    for( int j = 30 - length, k = 0; j<= 29; j++, k++ )
        if( isdigit( string[ k ] ) )
            integer[ j ] = string[ k ] - '0';
}

HugeInt HugeInt::operator+( const HugeInt &op2 ) const
{
    HugeInt temp;
    int carry = 0;

    for( int i = 29; i >= 0; i-- )
    {
        temp.integer[ i ] = integer[ i ] + op2.integer[ i ] + carry;

        if( temp.integer[ i ] > 9 )
        {
            temp.integer[ i ] %= 10;
            carry = 1;
        }
        else
            carry = 0;
    }

    return temp;
}


HugeInt HugeInt::operator+( int op2 ) const
{
    return *this + HugeInt( op2 );
}


HugeInt HugeInt::operator-( const HugeInt &hi ) const
{
    HugeInt temp, nil;
    short dif;
    int carry = 0;

    for( int i = 29; i >= 0; i-- )
    {
        // Em A - B, se A < B, retorna 0 (operacoes sem negativos)
        if( i == 0 && carry == -1 )
            return nil;

        dif = integer[ i ] - hi.integer[ i ] + carry;
        carry = 0;
        if( dif >= 0 )
            temp.integer[ i ] = dif;
        else
        {
            temp.integer[ i ] = dif + 10;
            carry = -1;
        }
    }
    return temp;
}


HugeInt HugeInt::operator-( int op2 ) const
{
    return *this - HugeInt( op2 );
}


bool HugeInt::operator==( const HugeInt &hi ) const
{
    int i;

    for( i = 0; i < 30; i++ )
    {
        if( integer[ i ] != hi.integer[ i ] )
            return false;
    }

    return true;
}


bool HugeInt::operator!=( const HugeInt &hi ) const
{
    int i;

    for( i = 0; i < 30; i++ )
    {
        if( integer[ i ] != hi.integer[ i ] )
            return true;
    }

    return false;
}


HugeInt HugeInt::operator*( const HugeInt &hi ) const
{
    HugeInt soma, zero;
    HugeInt it(hi);

    for( ; it != zero; it = it - 1 )
    {
        soma = soma + *this;
    }

    return soma;
}


bool HugeInt::operator<( const HugeInt &hi ) const
{
    int i;

    for( i = 0; i < 30; i++ )
    {
        if( integer[ i ] == hi.integer[ i ] )
            continue;
        if( integer[ i ] < hi.integer[ i ] )
            return true;
        else
            return false;
    }

    return false;
}


HugeInt HugeInt::operator/( const HugeInt &hi ) const
{
    HugeInt result;
    HugeInt copy( *this );

    while( hi < copy )
    {
        copy = copy - hi;
        result = result + 1;
    }

    if( hi == copy )
    {
        result = result + 1;
    }

    return result;
}


ostream & operator<<( ostream &output, const HugeInt &num )
{
    int i;

    for( i = 0; (num.integer[ i ] == 0 ) && ( i <= 29 ); i++ )
        ;

    if( i == 30 )
        output << 0;
    else
        for( ; i <= 29; i++ )
            output << num.integer[ i ];

    return output;
}


